'''
分发的源代码（2）
•read decision table from csvfile函数
•参数1个：要读取的csv文件的名称
•返回值：表示制作的决定表的列表
•make partition函数
•参数2：表示决定表的列表、属性集合的列表
•返回值：表示创建的分割的列表
•make positive region函数
•参数3：表示决定表的列表、表示分割的列表、表示决定类的列表
•返回值：表示正区域的集合（set型）
•calc quality of apploximation by partition函数
•参数3：表示决定表的列表、表示分割的列表、表示决定类的列表
•返回值：近似质量值

分发的源代码（1）
• quick_reduct_hinagata.py
•实现QuickReduct算法的源代码
•需要部分填空，请各自安装
• roughset.py
• quick_reduct_hinagata.py移动最小限度需要的自作函数
固定的源代码
•没有填空部分，请直接使用
'''

# 用于读取csv文件并创建决定表的函数
def read_decision_table_from_csvfile(file):
    # •参数1个：要读取的csv文件的名称
    # •返回值：表示制作的决定表的列表
    with open(file, "r") as fileobj:
        dt = []  # 初始化表示决定表的列表
        for num_obj, row in enumerate(fileobj):
            # 删除换行和空白等多余字符
            row = row.strip()
            tmp = row.split(",")
            tmp2 = []
            # 将决定表中的值转换为int型
            for value in tmp:
                if value.isdigit() == True:
                    tmp2.append(int(value))
                else:
                    tmp2.append(value)
            # 将行作为元组添加到dt
            dt.append(tuple(tmp2))
        #num_attr =len(dt[0]) - 1  # 属性个数为列数-1
        #numbers = tuple(range(0, num_attr+1))  # 选择表示属性编号的元组
        #dt.insert(0, numbers)                  # 插入到决定表的开头
        return dt

dt = read_decision_table_from_csvfile('./zoo-type.csv')
d = set()
d.add(len(dt[0])-1)
print(d)

# 根据属性id的集合attributes ids创建全体集合的分割的函数
def make_partition(dt, attributes_ids):
    # •参数2：表示决定表的列表、属性集合的列表
    # •返回值：表示创建的分割的列表
    partition = []
    univ_ids = set(range(1, len(dt)))  # 目标id的集合（工作用）       #文件的行数101-1
    print(univ_ids)
    while True:
        eq = set()  # 初始化要创建的 同值类，也就是值相同的
        try:
            item = univ_ids.pop()  # 取出一个对象id
            print(item,'item')
        except KeyError:
            break  # 因为univ ids变空了，所以作业结束
        except:
            print("Error!")
            return None
        eq.add(item)  # 添加item
        print(eq,'eq1')
        print(attributes_ids,'attributes_ids')          #文件的列数-1
        # 在attributes ids中包含的所有属性中，寻找与item值相同的对象
        for element in univ_ids:    #101
            flag = True  # 假设element和item值相等
            print('ttttt')
            for attr in attributes_ids:     #17
                # 检查属性attra的值
                print('dt[element][attr]', dt[element][attr])
                print('dt[item][attr]', dt[item][attr])
                if dt[element][attr] != dt[item][attr]:
                    flag = False  # 因为element和item的attr值不同
                    print('fffff')
                    break         # 对element的处理结束
                print('********')
            if flag == True:     # 因为element和item的值真的是相等的
                eq.add(element)  # element是item的同类要素
                print(eq,'eq2')
        # 因为item的同值类eq完成了，所以追加到partition
        partition.append(eq)
        print(partition,'partition')
        # 因为没有必要调查eq的要素，所以从univ ids中删除
        univ_ids.difference_update(eq)
    return partition    # 列表

dec_class = make_partition(dt, d)

# 决定表dt的分割partition创建正区域pos的函数
def make_positive_region(dt, partition, dec_class):
    # •参数3：表示决定表的列表、表示分割的列表、表示决定类的列表
    # •返回值：表示正区域的集合（set型）
    pos = set()  # 初始化正区域
    # 寻找包含partition中包含的同值类的决定类
    for eq in partition:
        for dc in dec_class:
            if eq.issubset(dc):  # 如果等值类eq包含在确定类dc中
                pos.update(eq)   # eq的元素包含在正区域中
    return pos

# 通过划分partition计算近似质量的函数
def calc_quality_of_approximation_by_partition(dt, partition, dec_class):
    # •参数3：表示决定表的列表、表示分割的列表、表示决定类的列表
    # •返回值：近似质量值
    pos = make_positive_region(dt, partition, dec_class)  # 创建正则区域
    return len(pos) / (len(dt)-1)  # 近似质量=正区域元素数/决定表元素数

# qs = make_partition(dt, cond_ids)
# print(qs)
# # 调用计算近似质量的函数
# gamma_c = rs.calc_quality_of_approximation_by_partition(dt, qs, dec_class)


